package com.highspeed.bdk.controller.gateway;

import com.bianmaba.spring.data.jpa.domain.Result;
import com.bianmaba.spring.mvc.method.support.annotations.JSON;
import com.highspeed.bdk.gateway.Util;
import com.highspeed.bdk.gateway.socket.analyze.message.gui.base.MessageResolver;
import com.highspeed.bdk.gateway.socket.analyze.message.gui.resolver.InitFbDataResolver0x02;
import com.highspeed.bdk.gateway.socket.analyze.message.gui.resolver.PhyUnderLogicLinkResolver0x0F;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.*;

@RestController
@RequestMapping(value = "gate_way", method = RequestMethod.POST)
@Api(tags = "网关")
public class GateWayController {

    @ApiOperation(value = "连接网关", notes = "连接网关时可能会失败")
    @ApiImplicitParams({@ApiImplicitParam(name = "ip", value = "ip", dataType = "string", paramType = "query"), @ApiImplicitParam(name = "port", value = "port", dataType = "int", paramType = "query")})
    @JSON
    @RequestMapping(value = "connect", method = RequestMethod.POST)
    public Result connectGateWay(String ip, Integer port) {
        if (ip == null || port == null) {
            return new Result(false, "参数不合法");
        }
        Random random = new Random();
        if (random.nextBoolean()) {
            return new Result(true, "连接成功");
        } else {
            return new Result(false, "连接失败");
        }
    }

    @ApiOperation(value = "断开网关连接", notes = "断开连接时可能失败")
    @ApiImplicitParams({@ApiImplicitParam(name = "ip", value = "ip", dataType = "string", paramType = "query"), @ApiImplicitParam(name = "port", value = "port", dataType = "int", paramType = "query")})
    @JSON
    @RequestMapping(value = "disconnect", method = RequestMethod.POST)
    public Result disconnectGateWay(String ip, Integer port) {
        if (ip == null || port == null) {
            return new Result(false, "参数不合法");
        }
        Random random = new Random();
        int n = random.nextInt();
        if (random.nextBoolean()) {
            return new Result(true, "连接成功");
        } else {
            return new Result(false, "连接失败");
        }
    }

    @ApiOperation(value = "下发部署表")
    @ApiImplicitParam(name = "id", value = "部署表id", dataType = "int", paramType = "query")
    @JSON
    @RequestMapping(value = "issued_deploy", method = RequestMethod.POST)
    public Result issuedDeploy(Integer id) {
        if (id == null) {
            return new Result(false, "部署表id为空");
        }
        Random random = new Random();
        if (random.nextBoolean()) {
            return new Result(true, "下发成功");
        } else {
            return new Result(false, "下发失败");
        }
    }

    @ApiOperation(value = "下发预制表")
    @ApiImplicitParam(name = "id", value = "预制表id", dataType = "int", paramType = "query")
    @JSON
    @RequestMapping(value = "issued_preset", method = RequestMethod.POST)
    public Result issuedPreset(Integer id) {
        if (id == null) {
            return new Result(false, "预制表id为空");
        }
        Random random = new Random();
        if (random.nextBoolean()) {
            return new Result(true, "下发成功");
        } else {
            return new Result(false, "下发失败");
        }
    }

    @ApiOperation(value = "查看两个处理单元的完整路径")
    @ApiImplicitParams({@ApiImplicitParam(name = "startCpuId", value = "起始处理单元id", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "endCpuId", value = "目标处理单元id", dataType = "int", paramType = "query")})
    @RequestMapping(value = "view_complete_path", method = RequestMethod.POST)
    public Result viewCompletePath(Integer startCpuId, Integer endCpuId) {
        Random random = new Random();
        List list = new ArrayList();
        Map row = new HashMap();
        list.add(row);
        row.put("startCpuId", startCpuId);
        row.put("startPort", random.nextInt(9999));
        row.put("endCpuId", endCpuId);
        row.put("endPort", random.nextInt(9999));
        row.put("flow", random.nextInt(99999));
        Result result = new Result(row);
        return result;
    }

    @ApiOperation(value = "查看CPU信息")
    @ApiImplicitParams({@ApiImplicitParam(name = "cpuId", value = "cpuId", dataType = "string", paramType = "query"), @ApiImplicitParam(name = "type", value = "类型", dataType = "int", paramType = "query")})
    @RequestMapping(value = "view_cpu_info", method = RequestMethod.POST)
    public Result viewCpuInfo(Integer cpuId, Integer type) {
        Result result = new Result();
        if (cpuId == null || type == null) {
            result.setSuccess(false);
            result.setResult("参数不合法，为空");
            return result;
        }

        Map<String, Object> results = new HashMap<>();
        String[] titleNames = {"设备ID", "目标ID", "入端口ID", "出端口ID", "下一跳ID"};
        List list = new ArrayList();
        for (int i = 0; i < titleNames.length; i++) {
            Map<String, Object> titleMap = new HashMap<>();
            titleMap.put("index", titleNames[i]);
            list.add(titleMap);
        }
        results.put("title", list);
        Random random = new Random();
        List<Map<String, Object>> values = new ArrayList<>();

        //返回五条数据
        for (int row = 0; row < 5; row++) {
            Map<String, Object> value = new HashMap<>();
            values.add(value);
            for (int i = 0; i < titleNames.length; i++) {
                int n = random.nextInt(999);
                value.put(titleNames[i], n);
            }
        }
        results.put("result", values);
        result.setData(results);
        return result;
    }

    @ApiOperation(value = "控制台命令下发")
    @ApiImplicitParams({@ApiImplicitParam(name = "command", value = "命令", dataType = "string", paramType = "query")})
    @RequestMapping(value = "issued_command", method = RequestMethod.POST)
    public Result issuedCommand(String command) {
        if (command == null) {
            return new Result(false, "下发命令为空,下发失败");
        }
        Random random = new Random();
        if (random.nextBoolean()) {
            return new Result(true, "下发命令成功");
        }
        return new Result(false, "下发命令失败");
    }

    @ApiOperation(value = "查看路由表项")
    @ApiImplicitParams({@ApiImplicitParam(name = "cpuId", value = "cpuId", dataType = "int", paramType = "query")})
    @RequestMapping(value = "view_route_table", method = RequestMethod.POST)
    public Result viewRouteTable(Integer cpuId) {
        if (cpuId == null) {
            return new Result(false, "查看路由表项失败，cupId为空");
        }
        Result result = new Result();
        Map<String, Object> results = new HashMap<>();
        String[] titleNames = {"设备ID", "目标ID", "入端口ID", "出端口ID", "下一跳ID"};
        List list = new ArrayList();
        for (int i = 0; i < titleNames.length; i++) {
            Map<String, Object> titleMap = new HashMap<>();
            titleMap.put("index", titleNames[i]);
            list.add(titleMap);
        }
        results.put("title", list);
        Random random = new Random();
        List<Map<String, Object>> values = new ArrayList<>();

        //返回五条数据
        for (int row = 0; row < 5; row++) {
            Map<String, Object> value = new HashMap<>();
            values.add(value);
            for (int i = 0; i < titleNames.length; i++) {
                int n = random.nextInt(999);
                if (titleNames[i].equals("设备ID")) {
                    value.put(titleNames[i], 1);
                } else {
                    value.put(titleNames[i], n);
                }
            }
        }
        results.put("result", values);
        result.setData(results);
        return result;
    }

    @ApiOperation(value = "查看物理链路属性")
    @ApiImplicitParams({@ApiImplicitParam(name = "startRionetId", value = "起始处理单元ID", dataType = "int", paramType = "query"), @ApiImplicitParam(name = "startPortId", value = "起始处理单元端口", dataType = "int", paramType = "query")
            , @ApiImplicitParam(name = "endRionetId", value = "目标处理单元ID", dataType = "int", paramType = "query"), @ApiImplicitParam(name = "endPortId", value = "目标处理单元ID", dataType = "int", paramType = "query")})
    @RequestMapping(value = "view_phylink_props", method = RequestMethod.POST)
    public Result viewPhyLinkProps(Integer startRionetId, Integer startPortId, Integer endRionetId, Integer endPortId) {

        Result result = new Result();
        if (startRionetId == null || startPortId == null || endRionetId == null || endPortId == null) {
            result.setSuccess(false);
            result.setResult("参数不合法，为空");
            return result;
        }
        Map map = new HashMap();

        //物理链路
        Map phyLink = new HashMap();
        phyLink.put("phyLinkId", 11);
        phyLink.put("backUp", 1);
        phyLink.put("linkDown", 0);
        phyLink.put("linkMode", "4X");
        phyLink.put("linkQuality", 0);
        map.put("phyLink", phyLink);

        Map propsA = new HashMap();
        //A端口属性
        propsA.put("netId", 11);
        propsA.put("protId", 1);
        propsA.put("portBmode", 4);
        map.put("portAprop", propsA);

        //B端口属性
        Map propsB = new HashMap();
        propsB.put("netId", 14);
        propsB.put("protId", 1);
        propsB.put("portBmode", 3);
        map.put("portBprop", propsB);

        //端口A统计信息
        Map portAstatistics = new HashMap();
        portAstatistics.put("inputPackets", 7236495);
        portAstatistics.put("inputReTransmissionNum", 1258);
        portAstatistics.put("input4Bytes", 47029920);
        portAstatistics.put("outputPackets", 7954099);
        portAstatistics.put("outputReTransmissionNum", 8390343);
        portAstatistics.put("output4Bytes", 104866375);
        portAstatistics.put("inputBandWidth", "1.446 M/S");
        portAstatistics.put("inputReTransmissionRate", 13);
        portAstatistics.put("outputBandWidth", "4.234 M/S");
        portAstatistics.put("outputReTransmissionRate", 13);
        map.put("portAstatistics", portAstatistics);

        //端口B统计信息
        Map portBstatistics = new HashMap();
        portBstatistics.put("inputPackets", 7236495);
        portBstatistics.put("inputReTransmissionNum", 1258);
        portBstatistics.put("input4Bytes", 47029920);
        portBstatistics.put("outputPackets", 7954099);
        portBstatistics.put("outputReTransmissionNum", 8390343);
        portBstatistics.put("output4Bytes", 104866375);
        portBstatistics.put("inputBandWidth", "1.446 M/S");
        portBstatistics.put("inputReTransmissionRate", 13);
        portBstatistics.put("outputBandWidth", "4.234 M/S");
        portBstatistics.put("outputReTransmissionRate", 13);
        map.put("portBstatistics", portBstatistics);

        result.setData(map);
        return result;
    }

    @ApiOperation(value = "打开监控，即初始化网络拓扑结构", notes = "暂时未配置任何请求参数，不保证以后会添加请求参数")
    @RequestMapping(value = "init_toplogical", method = RequestMethod.POST)
    public Result initToplogical() {
        Result result = new Result();
        ClassLoader classLoader = getClass().getClassLoader();
        URL url = classLoader.getResource("查询初始化后网络状态_操作号2_参数[].dat");
        try {
            File file = new File(URLDecoder.decode(url.getFile(), "utf-8"));
            byte[] response = Util.getContent(file.getPath());
            MessageResolver resolver = new InitFbDataResolver0x02();
            Map<String, Object> objects = resolver.resolve(response);
            result.setData(objects.get("result"));
//          return  getBoards();
//          return   getCpusByBoardId("520");
            return result;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

//    @ApiOperation(value = "获得所有的板卡信息以及板卡之间的连接关系", notes = "暂时未配置任何请求参数，不保证以后会添加请求参数")
//    @RequestMapping(value = "list_boards", method = RequestMethod.POST)
//    public Result getBoards() {
//        Result result = new Result();
//        ClassLoader classLoader = getClass().getClassLoader();
//        URL url = classLoader.getResource("查询初始化后网络状态_操作号2_参数[].dat");
//        try {
//            File file = new File(URLDecoder.decode(url.getFile(), "utf-8"));
//            byte[] response = Util.getContent(file.getPath());
//            MessageResolver resolver = new InitFbDataResolver0x02();
//            Map<String, Object> objects = resolver.resolve(response);
//            Map finalResult = new HashMap();
//            Map tempResult = (Map) objects.get("result");
//
//            //获取连接
//            List<Map> phyLinks = (List<Map>) tempResult.get("phyLinks");
//
//            //获取主板
//            List<Map> boards = (List<Map>) tempResult.get("boards");
//            finalResult.put("boards", boards);
//            List<Map> boardLinks = new ArrayList<>();
//            Map filter = new HashMap();
//            for (Map outer : boards) {
//                outer.put("hasProgram", new Random().nextBoolean());
//                for (Map inner : boards) {
//                    if (outer.get("boardName").equals(inner.get("boardName"))) {
//                        continue;
//                    }
//                    List<Map> outerCpus = (List<Map>) outer.get("cpus");
//                    List<Map> innerCpus = (List<Map>) inner.get("cpus");
//                    out:
//                    for (Map outerCpu : outerCpus) {
//                        for (Map innerCpu : innerCpus) {
//                            String route1 = "" + outerCpu.get("rioNetId") + innerCpu.get("rioNetId");
//                            String route2 = "" + innerCpu.get("rioNetId") + outerCpu.get("rioNetId");
//                            for (Map phylink : phyLinks) {
//                                String temp = "" + phylink.get("startRionetId") + phylink.get("endRionetId");
//                                if (route1.equals(temp) || temp.equals(route2)) {
//                                    String key = "" + outer.get("boardId") + inner.get("boardId");
//                                    if (!filter.containsKey(key)) {
//                                        String tempkey = "" + inner.get("boardId") + outer.get("boardId");
//                                        if (!filter.containsKey(tempkey)) {
//                                            Map boardLink = new HashMap();
//                                            boardLinks.add(boardLink);
//                                            System.out.println(temp);
//                                            boardLink.put("startBoardId", outer.get("boardId"));
//                                            boardLink.put("endBoardId", inner.get("boardId"));
//                                            boardLink.put("status", "数据总线");
//                                            filter.put(key, key);
//                                            filter.put(tempkey, tempkey);
//                                        }
//                                    }
//                                    System.out.println(outer.get("boardName") + "==========" + inner.get("boardName"));
//                                    break out;
//                                }
//                            }
//                        }
//                    }
//                }
//            }
//            finalResult.put("boardLinks", boardLinks);
//            for (Map board : boards) {
//                board.remove("cpus");
//            }
//            result.setData(finalResult);
//            return result;
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//        return null;
//    }


    @ApiOperation(value = "获得所有的板卡信息以及板卡之间的连接关系", notes = "暂时未配置任何请求参数，不保证以后会添加请求参数")
    @RequestMapping(value = "list_boards", method = RequestMethod.POST)
    public Result getBoards() {
        Random r = new Random();
        String[] status = {"控制总线", "数据总线", "未通电总线"};
        Result result = new Result();
        List<Map> machineBoxs = new ArrayList<>();
        result.setData(machineBoxs);
        for (int i = 1; i < 3; i++) {
            Map machineBox = new HashMap();
            machineBox.put("machineBoxName", "机箱" + i);
            machineBoxs.add(machineBox);
            List<Map> boards = new ArrayList<>();
            machineBox.put("boards", boards);
            int boardNum = 4;
            if (i == 1) {
                boardNum = 32;
            }
            for (int j = 1; j <= boardNum; j++) {
                Map board = new HashMap();
                board.put("boardName", j);
                board.put("slotNum", j);
                if (j % 2 == 0) {
                    board.put("hasProgram", true);
                } else {
                    board.put("hasProgram", false);
                }
                board.put("boardId", j);
                boards.add(board);
            }
            List<Map> boardLinks = new ArrayList<>();
            machineBox.put("boardLinks", boardLinks);
            for (int j = 1; j < boardNum; j++) {
                Map boardLink = new HashMap();
                boardLink.put("startBoardId", j);
                boardLink.put("endBoardId", j + 1);
                boardLink.put("status", status[r.nextInt(2)]);
                boardLinks.add(boardLink);
            }
        }
        return result;
    }

    @ApiOperation(value = "根据boardId获取该板卡下面的所有CPU以及CPU的连接关系", notes = "参数为板卡id")
    @ApiImplicitParam(name = "boardId", value = "选中的板卡ID", dataType = "int", paramType = "query")
    @RequestMapping("get_cpus_by_boardId")
    public Result getCpusByBoardId(String boardId) {
        String[] boardIds = {"520", "1328", "1320"};
        Integer boardIdIn = Integer.valueOf(boardId);
        boardId = boardIds[boardIdIn % 3];
        Result result = new Result();
        Map finalResult = new HashMap();
        ClassLoader classLoader = getClass().getClassLoader();
        URL url = classLoader.getResource("查询初始化后网络状态_操作号2_参数[].dat");
        try {
            File file = new File(URLDecoder.decode(url.getFile(), "utf-8"));
            byte[] response = Util.getContent(file.getPath());
            MessageResolver resolver = new InitFbDataResolver0x02();
            Map<String, Object> objects = resolver.resolve(response);
            Map tempResult = (Map) objects.get("result");
            Random random = new Random();

            //获取主板
            List<Map> boards = (List<Map>) tempResult.get("boards");
            List<Map> physicalLinks = (List<Map>) tempResult.get("phyLinks");
            List<Map> tempLinks = new ArrayList<>();
            for (Map outer : boards) {
                if (boardId.equals("" + outer.get("boardId"))) {
                    boolean hasProgram = false;
                    if (boardIdIn % 2 == 0) {
                        hasProgram = true;
                    }
                    List<Map> cpus = (List<Map>) outer.get("cpus");
                    finalResult.put("cpus", cpus);
                    Map<String, String> rionetIds = new HashMap<>();
                    for (Map cpu : cpus) {
                        rionetIds.put("" + cpu.get("rioNetId"), "" + cpu.get("rioNetId"));
                    }
                    int cpuNum = 0;
                    for (Map cpu : cpus) {
                        if (!hasProgram) {
                            cpu.put("hasApp", false);
                        } else {
                            cpu.put("hasApp", cpuNum % 2 == 0 ? true :false);
                        }
                        cpuNum++;
                        String rioNetId = cpu.get("rioNetId") + "";
                        for (Map physicalLink : physicalLinks) {
                            String startRioNetId = physicalLink.get("startRionetId") + "";
                            String endRioNetId = physicalLink.get("endRionetId") + "";
                            if (startRioNetId.equals(rioNetId)) {
                                Map temp = copyMap(physicalLink);
                                if (!rionetIds.containsKey(physicalLink.get("endRionetId") + "")) {
                                    temp.put("endRionetId", "-1");
                                    temp.put("endPortId", "-1");
                                }
                                tempLinks.add(temp);
                                System.out.println(temp);
                            } else if (endRioNetId.equals(rioNetId)) {
                                Map temp = copyMap(physicalLink);
                                if (!rionetIds.containsKey(physicalLink.get("startRionetId") + "")) {
                                    temp.put("startRionetId", "-1");
                                    temp.put("startPortId", "-1");
                                }
                                tempLinks.add(temp);
                            }
                        }
                    }
                    break;
                }
            }
            tempLinks = filter(tempLinks);
            finalResult.put("cpuLinks", tempLinks);
            result.setData(finalResult);
            return result;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public Map copyMap(Map map) {
        Map temp = new HashMap();
        temp.putAll(map);
        return temp;

    }

    public List<Map> filter(List<Map> list) {
        List<Map> result = new ArrayList<>();
        Map map = new HashMap();
        for (Map m : list) {
            String key = getKey(m);
            if (!map.containsKey(key)) {
                map.put(key, key);
                result.add(m);
            }
        }
        return result;
    }

    public String getKey(Map map) {
        String resultKey = "";
        for (Object key : map.keySet()) {
            resultKey += map.get(key);
        }
        return resultKey;
    }

    @ApiOperation(value = "全局搜索", notes = "参数只能填 0 1 2 3 4")
    @RequestMapping(value = "global_search", method = RequestMethod.POST)
    @ApiImplicitParams({@ApiImplicitParam(name = "no", value = "no", dataType = "string", paramType = "query")})
    public Result globalSearch(String no) {
        Result result = new Result();
        List<Map> list = new ArrayList<>();
        result.setData(list);
        if (no == null) {
            for (int i = 0; i < 5; i++) {
                Map<String, Object> line1 = new HashMap<>();
                list.add(line1);
                line1.put("no", i);
                line1.put("name", i);
                line1.put("type", "处理单元");
                line1.put("state", "");
                line1.put("remark", "");
            }
            Map<String, Object> line1 = new HashMap<>();
            line1.put("no", "1");
            line1.put("name", "1");
            line1.put("type", "板卡");
            line1.put("state", "");
            line1.put("remark", "");
            list.add(line1);
            return result;
        }
        Integer n = 0;
        try {
            n = Integer.valueOf(no);
        } catch (Throwable e) {
            return result;
        }
        if (n > 5) {
            return result;
        }
        Map<String, Object> line1 = new HashMap<>();
        line1.put("no", n);
        line1.put("name", n);
        line1.put("type", "处理单元");
        line1.put("state", "");
        line1.put("remark", "");
        return result;
    }

    @ApiOperation(value = "查看两个cpu直连路径")
    @RequestMapping(value = "view_direct_connection", method = RequestMethod.POST)
    @ApiImplicitParams({@ApiImplicitParam(name = "startCpuId", value = "起点CPUID", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "endCpuId", value = "终点cpuID", dataType = "int", paramType = "query")})
    public Result viewDirectConnection(Integer startCpuId, Integer endCpuId) {
        Result result = new Result();
        List<Map> connections = new ArrayList<>();
        Map map1 = new HashMap();
        map1.put("startRionetId", 0);
        map1.put("startPortId", 0);
        map1.put("endRionetId", 1);
        map1.put("endPortId", 10);
        connections.add(map1);

        Map map2 = new HashMap();
        map2.put("startRionetId", 1);
        map2.put("startPortId", 0);
        map2.put("endRionetId", 2);
        map2.put("endPortId", 8);
        connections.add(map2);

        Map map3 = new HashMap();
        map3.put("startRionetId", 2);
        map3.put("startPortId", 2);
        map3.put("endRionetId", 9);
        map3.put("endPortId", 14);
        connections.add(map3);

        Map map4 = new HashMap();
        map4.put("startRionetId", 9);
        map4.put("startPortId", 4);
        map4.put("endRionetId", 10);
        map4.put("endPortId", 0);
        connections.add(map4);

        result.setData(connections);
        return result;
    }

    @ApiOperation(value = "查看连接统计信息", notes = "物理链接和逻辑连接暂时使用同一个,flow表示流量信息，单位是bit,转化为k需要除以1024，转化为M需要除以1024*1024")
    @RequestMapping(value = "view_link_statistics", method = RequestMethod.POST)
    public Result viewPhysicalLinkStatics() {
        Result result = new Result();
        Result result1 = initToplogical();
        Map map = (Map) result1.getData();
        List<Map> phylinks = (List<Map>) map.get("phyLinks");
        Random random = new Random();
        List statitics = new ArrayList();
        if (!phylinks.isEmpty()) {
            for (Map m : phylinks) {
                Map newM = new HashMap();
                newM.put("startRionetId", m.get("startRionetId"));
                newM.put("startPortId", m.get("startPortId"));
                newM.put("endRionetId", m.get("endRionetId"));
                newM.put("endPortId", m.get("endPortId"));
                newM.put("flow", random.nextInt(10000) * 1024 * 1024);
                statitics.add(newM);
            }
        }
        result.setData(statitics);
        return result;
    }
}
